package com.personal.dao.template;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;

import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceUtils;

import com.personal.dao.cache.CacheKey;
import com.personal.dao.dialect.DaoDialect;
import com.personal.dao.exception.GetDialectErrorException;
import com.personal.dao.handler.BatchSqlHandler;
import com.personal.dao.handler.SqlHandler;
import com.personal.dao.sign.Signable;
import com.personal.dao.sql.BatchSql;
import com.personal.dao.sql.Sql;
import com.personal.dao.util.DaoUtil;
import com.personal.dao.util.JdbcUtil;

/**
 * DaoTemplateBean
 * 
 * @author qq
 *
 */
public class DaoTemplateBean implements DaoTemplate
{

	private static final Log LOG = LogFactory.getLog(DaoTemplateBean.class);

	protected DaoDialect dialect;

	protected boolean showSql;

	protected JdbcTemplate template;

	public void setDataSource(DataSource dataSource)
	{
		this.template = new JdbcTemplate(dataSource);
		this.dialect = getDialect(dataSource);
		if (this.dialect == null)
		{
			throw new GetDialectErrorException("获取" + dataSource + "的方言失败！");
		}
	}

	public void setShowSql(boolean showSql)
	{
		this.showSql = showSql;
	}

	@Override
	public <V> V execute(Sql sql, SqlHandler<V> handler)
	{
		if (showSql)
		{
			LOG.info("SQL：" + sql.getSql());
			LOG.info("PARAMS：" + Arrays.toString(sql.getParams()));
		}
		return handler.handleResult(this, sql);
	}

	@Override
	public <V> V execute(BatchSql sql, BatchSqlHandler<V> handler)
	{
		if (showSql)
		{
			LOG.info("SQL：" + sql.getSql());
			LOG.info("PARAMS：" + sql.getParams());
		}
		return handler.handleResult(this, sql);
	}

	@Override
	public <V> CacheKey createCacheKey(Signable... signables)
	{
		// 使用sql的签名和handler的类路径做唯一Id标识
		CacheKey cacheKey = new CacheKey();
		for (Signable signable : signables)
		{
			List<Object> list = signable.getSignFlags();
			if (!DaoUtil.isEmpty(list))
			{
				for (Object object : list)
				{
					cacheKey.update(object);
				}
			}
		}
		return cacheKey;
	}

	@Override
	public DaoDialect getDaoDialect()
	{
		return dialect;
	}
	
	@Override
	public JdbcTemplate geJdbcTemplate()
	{
		return template;
	}

	private DaoDialect getDialect(DataSource dataSource)
	{
		Connection connection = null;
		try
		{
			connection = DataSourceUtils.getConnection(dataSource);
			String e = connection.getMetaData().getDatabaseProductName();
			return DaoDialect.getDialect(e);
		} catch (SQLException e)
		{
			LOG.error(e.getMessage(), e);
			throw new GetDialectErrorException(e.getMessage(), e);
		} finally
		{
			JdbcUtil.releaseResource(template, connection, (PreparedStatement) null, (ResultSet) null);
		}

	}

}
